package com.fangs.lunbotu.banner;

import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

import androidx.core.view.ViewCompat;


import com.fangs.lunbotu.utils.ImageLoaderUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义banner控件
 */
public class BaseBanner extends LinearLayout {

    private ViewPagerBanner viewPager;
    //默认视频时间（考虑视频初加载无法获得时长）
    private final int vidoDelyed = 5000;
    //图片默认时间
    private int delyedTime = 2000;
    //默认显示位置
    private int autoCurrIndex = 0;
    private List<View> views;
    private BannerViewAdapter mAdapter;
    private OnPageChangeListener pageChangeListener;
    private OnClicked onClicked;
    private List<BannerPage> listBanner;
    private boolean onPause;
    private VideoTimeRunnable videoTimeRunnable;
    /**
     * 发消息，进行循环
     */
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            smoothed = false;
            viewPager.setCurrentItem(autoCurrIndex + 1, autoCurrIndex != 0);
            if (!smoothed) {
                mHandler.postDelayed(() -> viewPager.setCurrentItem(autoCurrIndex + 1, true), 2000);
            }
        }
    };
    private boolean smoothed = false; //笨办法 处理上层页面通过侧滑退出后 banner.onResume执行却仍 轮播中止问题
    //接受消息实现轮播
    private Handler mHandler = new Handler();
    private int mDownX = 0;
    private int mDownY = 0;
    private boolean horizontal = false;

    public BaseBanner(Context context) {
        super(context);
        init();
    }

    public BaseBanner(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public BaseBanner(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        videoTimeRunnable = new VideoTimeRunnable();
        LinearLayout.LayoutParams vp_param = new LinearLayout.LayoutParams(
                LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT);
        viewPager = new ViewPagerBanner(getContext());
        viewPager.setLayoutParams(vp_param);
        //增加翻页视差效果
        viewPager.setPageTransformer(true, (page, position) -> {
            int width = page.getWidth();
            if (position < -1) {
                page.setScrollX((int) (width * 0.8 * -1));
            } else if (position <= 1) {
                page.setScrollX((int) (width * 0.8 * position));
            } else {
                page.setScrollX((int) (width * 0.8));
            }
        }, ViewCompat.LAYER_TYPE_NONE);
        this.addView(viewPager);
    }

    /**
     * 设置ViewPager是否可以滑动，默认false不可滑动
     *
     * @param isSlide boolean;//
     **/
    public void setSlide(boolean isSlide) {
        viewPager.setSlide(isSlide);
    }

    public void setPageChangeListener(OnPageChangeListener pageChangeListener) {
        this.pageChangeListener = pageChangeListener;
    }

    public void setOnClicked(OnClicked clicked){
        this.onClicked = clicked;
    }

    /**
     * 设置滚动广告，图片，视频
     **/
    public void setBanner() {
        mAdapter = new BannerViewAdapter(views);
        viewPager.setAdapter(mAdapter);
        viewPager.setCurrentItem(autoCurrIndex, false);//跳转到指定页面
        mAdapter.setOnClicked(new BannerViewAdapter.OnClicked() {
            @Override
            public void onItemClicked(int positions) {
                onClicked.onItemClicked(positions);
            }
        });
        viewPager.addOnPageChangeListener(new ViewPagerBanner.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
            }

            @Override
            public void onPageSelected(int position) {
                //当前位置
                autoCurrIndex = position;
                if (pageChangeListener != null) {
                    // 此处 针对Banner中setDataList循环数组将首尾各加一条数据情况 将角标做对应处理
                    int p = position == 0 ? views.size() - 3 : (position == views.size() - 1 ? 0 : position - 1);
                    pageChangeListener.onPageSelected(p);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
                smoothed = true;
                //ViewPager跳转
                int pageIndex = autoCurrIndex;
                if (autoCurrIndex == 0) {
                    pageIndex = views.size() - 2;
                } else if (autoCurrIndex == views.size() - 1) {
                    pageIndex = 1;
                }

                if (views.size() == 1) { //此处考虑到 只有一项时触摸滑动也会触发当前方法 故做出判断避免角标越界
                    pageIndex = 0;
                }

                if (pageIndex != autoCurrIndex) {
                    //无滑动动画，直接跳转
                    viewPager.setCurrentItem(pageIndex, false);
                }

                if (state == 0) {
                    setAutoPlay(pageIndex);
                }
            }
        });
    }

    //开启自动循环
    public void setAutoPlay(int curPos) {
        View view1 = views.get(curPos);
        if (view1 instanceof MyVideoLayout) {
            MyVideoLayout videoLayout = (MyVideoLayout) view1;
            if (videoLayout.videoView.isPlaying()) {
                delyedTime = videoLayout.videoView.getDuration() - videoLayout.videoView.getCurrentPosition();
            } else {
                videoLayout.videoView.seekTo(0);
                videoLayout.videoView.start();
                delyedTime = videoLayout.videoView.getDuration();//单位毫秒（ms）
                videoTimeRunnable.getDelyedTime(videoLayout, runnable);
            }
        } else {
            delyedTime = listBanner.get(curPos).imgDelyed;
        }
        //移除自动计时
        mHandler.removeCallbacksAndMessages(null);
        if (views.size() > 1) {
            if (delyedTime < 0) { //此处默认是只有视频情况下才会拿不到时间
                mHandler.postDelayed(videoTimeRunnable, vidoDelyed);
            } else {
                mHandler.postDelayed(runnable, delyedTime);
            }
        }
    }

    /**
     * 设置数据
     *
     * @param dataList,//轮播数组
     * @param index,//插播地址，   -1时采用默认
     **/
    private void setDataList(List<BannerPage> dataList, int index) {
        listBanner = new ArrayList<>();

        if (index != -1) {
            autoCurrIndex = index;
        }

        if (dataList == null) {
            dataList = new ArrayList<>();
        }
        //用于显示的数组
        if (views == null) {
            views = new ArrayList<>();
        } else {
            views.clear();
        }

        //数据大于一条，才可以循环
        if (dataList.size() > 1) {
            if (autoCurrIndex < 0 || autoCurrIndex > dataList.size() - 1) {
                autoCurrIndex = 1;
            } else {
                autoCurrIndex++;
            }
            //循环数组，将首尾各加一条数据
            for (int i = 0; i < dataList.size() + 2; i++) {
                BannerPage bannerPage;
                if (i == 0) {
                    bannerPage = dataList.get(dataList.size() - 1);
                } else if (i == dataList.size() + 1) {
                    bannerPage = dataList.get(0);
                } else {
                    bannerPage = dataList.get(i - 1);
                }

                listBanner.add(bannerPage);

                if (bannerPage.isVideo) {
                    MyVideoLayout videoLayout = new MyVideoLayout(getContext(), false);
                    videoLayout.videoView.setUrl(bannerPage.url);
                    ImageLoaderUtils.display(getContext(), videoLayout.imageView, bannerPage.thum);
                    views.add(videoLayout);
                } else {
                    ImageView imageView = new ImageView(getContext());
                    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                    ImageLoaderUtils.display(getContext(), imageView, bannerPage.url);
                    views.add(imageView);
                }
            }
        } else if (dataList.size() == 1) {
            autoCurrIndex = 0;
            BannerPage bannerPage = dataList.get(0);
            listBanner.add(bannerPage);

            if (bannerPage.isVideo) {
                MyVideoLayout videoLayout = new MyVideoLayout(getContext(), true);
                videoLayout.videoView.setUrl(bannerPage.url);
                ImageLoaderUtils.display(getContext(), videoLayout.imageView, bannerPage.thum);
                views.add(videoLayout);
            } else {
                ImageView imageView = new ImageView(getContext());
                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                ImageLoaderUtils.display(getContext(), imageView, bannerPage.url);
                views.add(imageView);
            }
        } else {
            autoCurrIndex = 0;
            listBanner.add(new BannerPage("", 0));
            views.add(new LinearLayout(getContext()));
        }
    }

    /**
     * 设置数据并播放
     *
     * @param dataList,//轮播数组
     **/
    public void setDataPlay(List<BannerPage> dataList) {
        setDataPlay(dataList, -1);
    }

    /**
     * 设置数据并播放
     *
     * @param dataList,//轮播数组
     * @param index,//插播地址，   -1时采用默认
     **/
    public void setDataPlay(List<BannerPage> dataList, int index) {
        setDataList(dataList, index);
        setBanner();
        setAutoPlay(autoCurrIndex);
    }

    public void onResume() {
        if (onPause && views != null && views.size() > 1) {
            if (listBanner.get(autoCurrIndex).isVideo) {
                delyedTime = ((MyVideoLayout) views.get(autoCurrIndex)).videoLimitTime;
            } else {
                delyedTime = listBanner.get(autoCurrIndex).imgDelyed;
            }
            mHandler.removeCallbacksAndMessages(null);
            mHandler.postDelayed(runnable, delyedTime);
        }
        onPause = false;
    }

    public void onPause() {
        mHandler.removeCallbacksAndMessages(null);
        if (views != null && views.size() > 1) {
            if (autoCurrIndex == views.size() - 2) { //此处作用是配合 smoothed 字段的目的使用 都是东拼西凑的笨办法 因为并没有真正找到侧滑退出操作会中止首页轮播的原因
                autoCurrIndex = 0;
            }
        }

        onPause = true;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = (int) ev.getX();
                mDownY = (int) ev.getY();
                horizontal = false;
                mHandler.removeCallbacksAndMessages(null);
                break;
            case MotionEvent.ACTION_MOVE:
                int endX = (int) ev.getX();
                int endY = (int) ev.getY();
                int distanceX = Math.abs(endX - mDownX);
                int distanceY = Math.abs(endY - mDownY);
                horizontal = distanceX > 0 && distanceX > distanceY;
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_OUTSIDE:
                if (views != null && views.size() > 1) {
                    if (listBanner.get(autoCurrIndex).isVideo) {
                        MyVideoLayout videoLayout = (MyVideoLayout) views.get(autoCurrIndex);
                        delyedTime = videoLayout.videoView.getDuration() - videoLayout.videoView.getCurrentPosition();
                    } else {
                        delyedTime = listBanner.get(autoCurrIndex).imgDelyed;
                    }
                    mHandler.removeCallbacksAndMessages(null);
                    mHandler.postDelayed(runnable, delyedTime);
                }
                break;
            case MotionEvent.ACTION_UP:
                if (!horizontal && views != null && views.size() > 1) { // 如果水平滑动的话 会自动触发OnPageChangeListener启动轮播 故无须执行下面的代码
                    if (listBanner.get(autoCurrIndex).isVideo) {
                        MyVideoLayout videoLayout = (MyVideoLayout) views.get(autoCurrIndex);
                        delyedTime = videoLayout.videoView.getDuration() - videoLayout.videoView.getCurrentPosition();
                    } else {
                        delyedTime = listBanner.get(autoCurrIndex).imgDelyed;
                    }
                    mHandler.removeCallbacksAndMessages(null);
                    mHandler.postDelayed(runnable, delyedTime);
                }
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    public void destroy() {
        //说当参数为null时,删除所有回调函数和message
        // 这样做的好处是在Acticity退出的时候，可以避免内存泄露
        mHandler.removeCallbacksAndMessages(null);
        mHandler = null;
        videoTimeRunnable = null;
        runnable = null;
        if (views != null) {
            views.clear();
            views = null;
        }
        viewPager = null;
        mAdapter = null;
    }

    /**
     * 这个类，恩，获取视频长度，以及已经播放的时间
     */
    private class VideoTimeRunnable implements Runnable {

        private MyVideoLayout videoLayout;
        private Runnable runnable;

        public void getDelyedTime(MyVideoLayout videoLayout, Runnable runnable) {
            this.videoLayout = videoLayout;
            this.runnable = runnable;
        }

        @Override
        public void run() {
            int delyedTime = videoLayout.videoView.getDuration() - videoLayout.videoView.getCurrentPosition();
            mHandler.postDelayed(runnable, delyedTime >= 0 ? delyedTime : vidoDelyed);
        }
    }

    public interface OnPageChangeListener {

        void onPageSelected(int position);
    }

    public interface OnClicked{
        void onItemClicked(int positions);
    }
}
